#include "buff.h"
#include "stdlib.h"
#include "string.h"




#ifndef BOOTLOADER
    #include "rthw.h"
    #define IRQ_DISABLE() rt_base_t irq_stat=rt_hw_interrupt_disable( )
    #define IRQ_ENABLE()	rt_hw_interrupt_enable (irq_stat)
#else
	#define IRQ_DISABLE() { }
	#define IRQ_ENABLE()	{ }
#endif



int buff_init(data_buff *buff,int size,int use_frame,int frame_start,int frame_end)
{ 
    if(buff==0) return -1;
    if(buff->buff==0)
    {
        buff->buff=malloc(size);
        if(buff->buff==0) return -1;
        memset(buff->buff,0,sizeof(size));
        buff->buff_len= size;
        buff->use_frame=use_frame;
        buff->frame_start=frame_start;
        buff->frame_end=frame_end;
    }
    buff_clear(buff);
    return 0;
}


int buff_deinit(data_buff *buff)
{
    if(buff==0) return -1;
    if(buff->buff)
    {
        free(buff->buff);
        buff->buff=0;
        buff->buff_len=0;
    }
    return 0;
}


int buff_get_used(data_buff *buff)
{
    int ret=-1;
	IRQ_DISABLE();
    ret=buff->buff_used;
	IRQ_ENABLE();
    return ret;
}




int buff_save_byte(data_buff *buff,uint8_t data)
{
    if(buff==0) return -1;
	int ret=-1;
	IRQ_DISABLE();
	if((!buff->use_frame)||(data==buff->frame_start)) buff->active=1;
	if((buff->buff_used<buff->buff_len)&&buff->active)
	{
		buff->buff[buff->save_ptr]=data;
		buff->buff_used++;
		if((buff->use_frame)&&(data==buff->frame_end)) {
			buff->frame_num++;
			buff->active=0;
		}
		buff->save_ptr++;
		if (buff->save_ptr>=buff->buff_len)
			buff->save_ptr=0;
		ret= 0;
	}
	IRQ_ENABLE();
	return ret;
}


int buff_save_bytes(data_buff *buff,const uint8_t *data,int len)
{
    if(buff==0) return -1;
	int ret=-1;
	IRQ_DISABLE();
	if (buff->buff_used+len<=buff->buff_len)
    {
        while(len--)
        {
            ret=buff_save_byte(buff,*data);data++;
            if(ret!=0) break;
        }
    }
	IRQ_ENABLE();
	return ret;
}



int buff_read_byte(data_buff *buff,uint8_t *data)
{
    if(buff==0) return -1;
	int ret=-1;
	IRQ_DISABLE();
	if (((buff->frame_num)&&(buff->buff_used))||((!buff->use_frame)&&(buff->buff_used)))
	{
		*data=buff->buff[buff->read_ptr];
		buff->buff_used--;
		if((buff->use_frame)&&(*data==buff->frame_end)) buff->frame_num--;
		buff->read_ptr++;
		if (buff->read_ptr>=buff->buff_len)
			buff->read_ptr=0;
		ret= 0;
	}
	IRQ_ENABLE();
	return ret;
}



int buff_read_bytes(data_buff *buff,uint8_t *data,int len)
{
    if(buff==0) return -1;
	int ret=-1;
	IRQ_DISABLE();
	if (buff->buff_used>=len)
	{
        while(len--)
        {
            ret=buff_read_byte(buff,data);data++;
            if(ret!=0) break;
        }
	}
	IRQ_ENABLE();
	return ret;
}




int buff_clear(data_buff *buff)
{
    if(buff==0) return -1;
	IRQ_DISABLE();
	buff->buff_used=0;
	buff->read_ptr=0;
	buff->save_ptr=0;
	buff->frame_num=0;
	buff->active=0;
	IRQ_ENABLE();
	return 0;
}






